home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / mg2a_src.zip / WINDOW.C < prev    next >
C/C++ Source or Header  |  1988-08-23  |  10KB  |  400 lines

  1. /*
  2.  *        Window handling.
  3.  */
  4. #include    "def.h"
  5.  
  6. /*
  7.  * Reposition dot in the current
  8.  * window to line "n". If the argument is
  9.  * positive, it is that line. If it is negative it
  10.  * is that line from the bottom. If it is 0 the window
  11.  * is centered (this is what the standard redisplay code
  12.  * does).  If GOSREC is undefined, default is 0, so it acts like GNU.
  13.  * If GOSREC is defined, with no argument it defaults to 1
  14.  * and works like in Gosling.
  15.  */
  16. /*ARGSUSED*/
  17. reposition(f, n)
  18. {
  19. #ifndef GOSREC
  20.     curwp->w_force = (f & FFARG) ? (n>=0 ? n+1 : n) : 0;
  21. #else
  22.     curwp->w_force = n;
  23. #endif
  24.     curwp->w_flag |= WFFORCE;
  25.     sgarbf = TRUE;
  26.     return TRUE;
  27. }
  28.  
  29. /*
  30.  * Refresh the display. A call is made to the
  31.  * "ttresize" entry in the terminal handler, which tries
  32.  * to reset "nrow" and "ncol". They will, however, never
  33.  * be set outside of the NROW or NCOL range. If the display
  34.  * changed size, arrange that everything is redone, then
  35.  * call "update" to fix the display. We do this so the
  36.  * new size can be displayed. In the normal case the
  37.  * call to "update" in "main.c" refreshes the screen,
  38.  * and all of the windows need not be recomputed.
  39.  * Note that when you get to the "display unusable"
  40.  * message, the screen will be messed up. If you make
  41.  * the window bigger again, and send another command,
  42.  * everything will get fixed!
  43.  */
  44. /*ARGSUSED*/
  45. refresh(f, n)
  46. {
  47.     register WINDOW *wp;
  48.     register int    oldnrow;
  49.     register int    oldncol;
  50.  
  51.     oldnrow = nrow;
  52.     oldncol = ncol;
  53.     ttresize();
  54.     if (nrow!=oldnrow || ncol!=oldncol) {
  55.         wp = wheadp;            /* Find last.        */
  56.         while (wp->w_wndp != NULL)
  57.             wp = wp->w_wndp;
  58.         if (nrow < wp->w_toprow+3) {    /* Check if too small.    */
  59.             ewprintf("Display unusable");
  60.             return (FALSE);
  61.         }
  62.         wp->w_ntrows = nrow-wp->w_toprow-2;
  63.         sgarbf = TRUE;
  64.         update();
  65.         ewprintf("New size %d by %d", nrow, ncol);
  66.     } else
  67.         sgarbf = TRUE;
  68.     return TRUE;
  69. }
  70.  
  71. /*
  72.  * The command to make the next
  73.  * window (next => down the screen)
  74.  * the current window. There are no real
  75.  * errors, although the command does
  76.  * nothing if there is only 1 window on
  77.  * the screen.
  78.  */
  79. /*ARGSUSED*/
  80. nextwind(f, n)
  81. {
  82.     register WINDOW *wp;
  83.  
  84.     if ((wp=curwp->w_wndp) == NULL)
  85.         wp = wheadp;
  86.     curwp = wp;
  87.     curbp = wp->w_bufp;
  88.     return TRUE;
  89. }
  90.  
  91. #ifdef    GOSMACS
  92. /* not in Gnu Emacs */
  93. /*
  94.  * This command makes the previous
  95.  * window (previous => up the screen) the
  96.  * current window. There arn't any errors,
  97.  * although the command does not do a lot
  98.  * if there is 1 window.
  99.  */
  100. /*ARGSUSED*/
  101. prevwind(f, n)
  102. {
  103.     register WINDOW *wp1;
  104.     register WINDOW *wp2;
  105.  
  106.     wp1 = wheadp;
  107.     wp2 = curwp;
  108.     if (wp1 == wp2)
  109.         wp2 = NULL;
  110.     while (wp1->w_wndp != wp2)
  111.         wp1 = wp1->w_wndp;
  112.     curwp = wp1;
  113.     curbp = wp1->w_bufp;
  114.     return TRUE;
  115. }
  116. #endif
  117.  
  118. /*
  119.  * This command makes the current
  120.  * window the only window on the screen.
  121.  * Try to set the framing
  122.  * so that "." does not have to move on
  123.  * the display. Some care has to be taken
  124.  * to keep the values of dot and mark
  125.  * in the buffer structures right if the
  126.  * distruction of a window makes a buffer
  127.  * become undisplayed.
  128.  */
  129. /*ARGSUSED*/
  130. onlywind(f, n)
  131. {
  132.     register WINDOW *wp;
  133.     register LINE    *lp;
  134.     register int    i;
  135.  
  136.     while (wheadp != curwp) {
  137.         wp = wheadp;
  138.         wheadp = wp->w_wndp;
  139.         if (--wp->w_bufp->b_nwnd == 0) {
  140.             wp->w_bufp->b_dotp  = wp->w_dotp;
  141.             wp->w_bufp->b_doto  = wp->w_doto;
  142.             wp->w_bufp->b_markp = wp->w_markp;
  143.             wp->w_bufp->b_marko = wp->w_marko;
  144.         }
  145.         free((char *) wp);
  146.     }
  147.     while (curwp->w_wndp != NULL) {
  148.         wp = curwp->w_wndp;
  149.         curwp->w_wndp = wp->w_wndp;
  150.         if (--wp->w_bufp->b_nwnd == 0) {
  151.             wp->w_bufp->b_dotp  = wp->w_dotp;
  152.             wp->w_bufp->b_doto  = wp->w_doto;
  153.             wp->w_bufp->b_markp = wp->w_markp;
  154.             wp->w_bufp->b_marko = wp->w_marko;
  155.         }
  156.         free((char *) wp);
  157.     }
  158.     lp = curwp->w_linep;
  159.     i  = curwp->w_toprow;
  160.     while (i!=0 && lback(lp)!=curbp->b_linep) {
  161.         --i;
  162.         lp = lback(lp);
  163.     }
  164.     curwp->w_toprow = 0;
  165.     curwp->w_ntrows = nrow-2;        /* 2 = mode, echo.    */
  166.     curwp->w_linep    = lp;
  167.     curwp->w_flag  |= WFMODE|WFHARD;
  168.     return TRUE;
  169. }
  170.  
  171. /*
  172.  * Split the current window. A window
  173.  * smaller than 3 lines cannot be split.
  174.  * The only other error that is possible is
  175.  * a "malloc" failure allocating the structure
  176.  * for the new window.
  177.  */
  178. /*ARGSUSED*/
  179. splitwind(f, n)
  180. {
  181.     register WINDOW *wp;
  182.     register LINE    *lp;
  183.     register int    ntru;
  184.     register int    ntrd;
  185.     int        ntrl;
  186.     WINDOW        *wp1, *wp2;
  187.  
  188.     if (curwp->w_ntrows < 3) {
  189.         ewprintf("Cannot split a %d line window", curwp->w_ntrows);
  190.         return (FALSE);
  191.     }
  192.     if ((wp = (WINDOW *)malloc(sizeof(WINDOW))) == NULL) {
  193.         ewprintf("Can't get %d", sizeof(WINDOW));
  194.         return (FALSE);
  195.     }
  196.     ++curbp->b_nwnd;            /* Displayed twice.    */
  197.     wp->w_bufp  = curbp;
  198.     wp->w_dotp  = curwp->w_dotp;
  199.     wp->w_doto  = curwp->w_doto;
  200.     wp->w_markp = curwp->w_markp;
  201.     wp->w_marko = curwp->w_marko;
  202.     wp->w_flag  = 0;
  203.     wp->w_force = 0;
  204.     ntru = (curwp->w_ntrows-1) / 2;        /* Upper size        */
  205.     ntrl = (curwp->w_ntrows-1) - ntru;    /* Lower size        */
  206.     lp = curwp->w_linep;
  207.     ntrd = 0;
  208.     while (lp != curwp->w_dotp) {
  209.         ++ntrd;
  210.         lp = lforw(lp);
  211.     }
  212.     lp = curwp->w_linep;
  213.     if (ntrd <= ntru) {            /* Old is upper window. */
  214.         if (ntrd == ntru)        /* Hit mode line.    */
  215.             lp = lforw(lp);
  216.         curwp->w_ntrows = ntru;
  217.         wp->w_wndp = curwp->w_wndp;
  218.         curwp->w_wndp = wp;
  219.         wp->w_toprow = curwp->w_toprow+ntru+1;
  220.         wp->w_ntrows = ntrl;
  221.     } else {                /* Old is lower window    */
  222.         wp1 = NULL;
  223.         wp2 = wheadp;
  224.         while (wp2 != curwp) {
  225.             wp1 = wp2;
  226.             wp2 = wp2->w_wndp;
  227.         }
  228.         if (wp1 == NULL)
  229.             wheadp = wp;
  230.         else
  231.             wp1->w_wndp = wp;
  232.         wp->w_wndp   = curwp;
  233.         wp->w_toprow = curwp->w_toprow;
  234.         wp->w_ntrows = ntru;
  235.         ++ntru;                /* Mode line.        */
  236.         curwp->w_toprow += ntru;
  237.         curwp->w_ntrows     = ntrl;
  238.         while (ntru--)
  239.             lp = lforw(lp);
  240.     }
  241.     curwp->w_linep = lp;            /* Adjust the top lines */
  242.     wp->w_linep = lp;            /* if necessary.    */
  243.     curwp->w_flag |= WFMODE|WFHARD;
  244.     wp->w_flag |= WFMODE|WFHARD;
  245.     return TRUE;
  246. }
  247.  
  248. /*
  249.  * Enlarge the current window.
  250.  * Find the window that loses space. Make
  251.  * sure it is big enough. If so, hack the window
  252.  * descriptions, and ask redisplay to do all the
  253.  * hard work. You don't just set "force reframe"
  254.  * because dot would move.
  255.  */
  256. /*ARGSUSED*/
  257. enlargewind(f, n)
  258. {
  259.     register WINDOW *adjwp;
  260.     register LINE    *lp;
  261.     register int    i;
  262.  
  263.     if (n < 0)
  264.         return shrinkwind(f, -n);
  265.     if (wheadp->w_wndp == NULL) {
  266.         ewprintf("Only one window");
  267.         return FALSE;
  268.     }
  269.     if ((adjwp=curwp->w_wndp) == NULL) {
  270.         adjwp = wheadp;
  271.         while (adjwp->w_wndp != curwp)
  272.             adjwp = adjwp->w_wndp;
  273.     }
  274.     if (adjwp->w_ntrows <= n) {
  275.         ewprintf("Impossible change");
  276.         return FALSE;
  277.     }
  278.     if (curwp->w_wndp == adjwp) {        /* Shrink below.    */
  279.         lp = adjwp->w_linep;
  280.         for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
  281.             lp = lforw(lp);
  282.         adjwp->w_linep    = lp;
  283.         adjwp->w_toprow += n;
  284.     } else {                /* Shrink above.    */
  285.         lp = curwp->w_linep;
  286.         for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
  287.             lp = lback(lp);
  288.         curwp->w_linep    = lp;
  289.         curwp->w_toprow -= n;
  290.     }
  291.     curwp->w_ntrows += n;
  292.     adjwp->w_ntrows -= n;
  293.     curwp->w_flag |= WFMODE|WFHARD;
  294.     adjwp->w_flag |= WFMODE|WFHARD;
  295.     return TRUE;
  296. }
  297.  
  298. /*
  299.  * Shrink the current window.
  300.  * Find the window that gains space. Hack at
  301.  * the window descriptions. Ask the redisplay to
  302.  * do all the hard work.
  303.  */
  304. shrinkwind(f, n)
  305. {
  306.     register WINDOW *adjwp;
  307.     register LINE    *lp;
  308.     register int    i;
  309.  
  310.     if (n < 0)
  311.         return enlargewind(f, -n);
  312.     if (wheadp->w_wndp == NULL) {
  313.         ewprintf("Only one window");
  314.         return FALSE;
  315.     }
  316.     /*
  317.      * Bit of flakiness - KRANDOM means it was an internal call, and
  318.      * to be trusted implicitly about sizes.
  319.      */
  320.     if ( !(f & FFRAND) && curwp->w_ntrows <= n) {
  321.         ewprintf("Impossible change");
  322.         return (FALSE);
  323.     }
  324.     if ((adjwp=curwp->w_wndp) == NULL) {
  325.         adjwp = wheadp;
  326.         while (adjwp->w_wndp != curwp)
  327.             adjwp = adjwp->w_wndp;
  328.     }
  329.     if (curwp->w_wndp == adjwp) {        /* Grow below.        */
  330.         lp = adjwp->w_linep;
  331.         for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
  332.             lp = lback(lp);
  333.         adjwp->w_linep    = lp;
  334.         adjwp->w_toprow -= n;
  335.     } else {                /* Grow above.        */
  336.         lp = curwp->w_linep;
  337.         for (i=0; i<n && lp!=curbp->b_linep; ++i)
  338.             lp = lforw(lp);
  339.         curwp->w_linep    = lp;
  340.         curwp->w_toprow += n;
  341.     }
  342.     curwp->w_ntrows -= n;
  343.     adjwp->w_ntrows += n;
  344.     curwp->w_flag |= WFMODE|WFHARD;
  345.     adjwp->w_flag |= WFMODE|WFHARD;
  346.     return (TRUE);
  347. }
  348.  
  349. /*
  350.  * Delete current window. Call shrink-window to do the screen
  351.  * updating, then throw away the window.
  352.  */
  353. /*ARGSUSED*/
  354. delwind(f, n)
  355. {
  356.     register WINDOW *wp, *nwp;
  357.  
  358.     wp = curwp;            /* Cheap...        */
  359.     /* shrinkwind returning false means only one window... */
  360.     if (shrinkwind(FFRAND, wp->w_ntrows + 1) == FALSE)
  361.         return FALSE;
  362.     if (--wp->w_bufp->b_nwnd == 0) {
  363.         wp->w_bufp->b_dotp  = wp->w_dotp;
  364.         wp->w_bufp->b_doto  = wp->w_doto;
  365.         wp->w_bufp->b_markp = wp->w_markp;
  366.         wp->w_bufp->b_marko = wp->w_marko;
  367.     }
  368.     /* since shrinkwind did't crap out, we know we have a second window */
  369.     if (wp == wheadp) wheadp = curwp = wp->w_wndp;
  370.     else if ((curwp = wp->w_wndp) == NULL) curwp = wheadp;
  371.     curbp = curwp->w_bufp;
  372.     for (nwp = wheadp; nwp != NULL; nwp = nwp->w_wndp)
  373.         if (nwp->w_wndp == wp) {
  374.             nwp->w_wndp = wp->w_wndp;
  375.             break ;
  376.         }
  377.     free((char *) wp);
  378.     return TRUE;
  379. }
  380. /*
  381.  * Pick a window for a pop-up.
  382.  * Split the screen if there is only
  383.  * one window. Pick the uppermost window that
  384.  * isn't the current window. An LRU algorithm
  385.  * might be better. Return a pointer, or
  386.  * NULL on error.
  387.  */
  388. WINDOW    *
  389. wpopup() {
  390.     register WINDOW *wp;
  391.  
  392.     if (wheadp->w_wndp == NULL
  393.     && splitwind(FFRAND, 0) == FALSE)
  394.         return NULL;
  395.     wp = wheadp;                /* Find window to use    */
  396.     while (wp!=NULL && wp==curwp)
  397.         wp = wp->w_wndp;
  398.     return wp;
  399. }
  400.